package com.ithuangyl.aroute;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import androidx.fragment.app.Fragment;
import dalvik.system.DexFile;

public class ARouter {

    private Map<String, Class<? extends Activity>> ACTIVITY_MAP = new HashMap<>();
    private Map<String, Class<? extends Fragment>> FRAGMENT_MAP = new HashMap<>();
    private Context context;

    private ARouter() {
    }

    private static class Holder {
        private static final ARouter INSTANCE = new ARouter();
    }

    public static ARouter create() {
        return Holder.INSTANCE;
    }

    public boolean addActivity(String key, Class<? extends Activity> clazz) {
        if (!TextUtils.isEmpty(key) && clazz != null && !ACTIVITY_MAP.containsKey(key)) {
            ACTIVITY_MAP.put(key, clazz);
            return true;
        }
        return false;
    }

    public boolean addFragment(String key, Class<? extends Fragment> clazz) {
        if (!TextUtils.isEmpty(key) && clazz != null && !FRAGMENT_MAP.containsKey(key)) {
            FRAGMENT_MAP.put(key, clazz);
            return true;
        }
        return false;
    }

    public Class<? extends Fragment> getFragment(String key) {
        if (FRAGMENT_MAP.containsKey(key)) {
            return FRAGMENT_MAP.get(key);
        }
        return null;
    }

    public void init(Context context) {
        this.context = context;
        List<String> classNames = getClassName("com.ithuangyl.util");
        for (String className : classNames) {
            try {
                Class<?> aClass = Class.forName(className);
                if (IRouter.class.isAssignableFrom(aClass)) {
                    IRouter router = (IRouter) aClass.newInstance();
                    router.putActivity();
                } else if (IFragmentRouter.class.isAssignableFrom(aClass)) {
                    IFragmentRouter fragmentRouter = (IFragmentRouter) aClass.newInstance();
                    fragmentRouter.putFragment();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private List<String> getClassName(String packageName) {
        List<String> classList = new ArrayList<>();
        String path;
        try {
            path = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0).sourceDir;
            DexFile dexFile = new DexFile(path);
            Enumeration entries = dexFile.entries();
            while (entries.hasMoreElements()) {
                String name = (String) entries.nextElement();
                if (name.contains(packageName)) {
                    classList.add(name);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return classList;
    }


    public void jumpActivity(Activity activity, String key, Bundle bundle) {
        Class<? extends Activity> clazz = ACTIVITY_MAP.get(key);
        if (clazz != null) {
            Intent intent = new Intent();
            intent.setClass(activity, clazz);
            if (bundle != null) {
                intent.putExtras(bundle);
            }
            activity.startActivity(intent);
        }
    }

    public void jumpActivityForResult(Activity activity, String key, Bundle bundle, int reqCode) {
        Class<? extends Activity> clazz = ACTIVITY_MAP.get(key);
        if (clazz != null) {
            Intent intent = new Intent();
            intent.setClass(activity, clazz);
            if (bundle != null) {
                intent.putExtras(bundle);
            }
            activity.startActivityForResult(intent, reqCode);
        }
    }

    public Fragment createFragment(String key, Bundle args) {
        Class<? extends Fragment> clazz = FRAGMENT_MAP.get(key);
        Fragment fragment = null;
        if (clazz != null) {
            try {
                fragment = clazz.newInstance();
                if (args != null) {
                    fragment.setArguments(args);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
        return fragment;
    }
}
